package xin.pms.controller;

import com.alibaba.fastjson.JSONObject;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mobile.device.Device;
import org.springframework.security.authentication.AccountExpiredException;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.*;
import xin.common.http.response.Response;
import xin.core.AppConstant;
import xin.core.jwt.*;
import xin.lms.service.AccessLogService;
import xin.lms.model.AccessLog;
import xin.pms.service.UserService;
import xin.pms.ui.AddUser;
import xin.pms.ui.UiUser;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * <pre>
 * Login Controller
 * </pre>
 *
 * @author lixin_ma@outlook.com
 * @version 1.0
 * @since 2018/7/28 22:28
 */
@RestController
@Api(value = "xin-auth", description = "授权", position = 2)
@RequestMapping
@Slf4j
public class AuthController {

    @Autowired
    private AuthenticationManager authenticationManager;

    @Autowired
    private JwtTokenService jwtTokenUtil;

    @Autowired
    private JwtUserDetailsService service;

    @Autowired
    private AccessLogService accessLogService;

    @Autowired
    private UserService userService;


    @ApiOperation(value = "登录", notes = "登录", response = JSONObject.class)
    @PostMapping("login")
    public JwtAuthenticationResponse login(@RequestBody JwtAuthenticationRequest request, Device device, HttpServletRequest servletRequest) {
        final Authentication authentication = authenticationManager.authenticate(
                new UsernamePasswordAuthenticationToken(
                        request.getUsername(),
                        request.getPassword()
                )
        );
        SecurityContextHolder.getContext().setAuthentication(authentication);
        final JwtUser jwtUser = (JwtUser)service.loadUserByUsername(request.getUsername());


        /**
         * 登录日志
         */
        Date loginTime = new Date(System.currentTimeMillis());
        AccessLog accessLog = new AccessLog();
        accessLog.setUserName(request.getUsername());
        accessLog.initDetail(servletRequest);
        accessLog.setLoginTime(loginTime);
        accessLogService.save(accessLog);

        Map<String, Object> claims =  new HashMap<>();
        claims.put(AppConstant.LOGIN_LOG_ID,accessLog.getId());
        claims.put(AppConstant.USER_ID,jwtUser.getId());
        final String token = jwtTokenUtil.generateToken(jwtUser,device,claims);
        return new JwtAuthenticationResponse(token,request.getUsername(),Boolean.TRUE,loginTime);
    }

    @ApiOperation(value = "刷新Token", notes = "刷新Token", response = JwtAuthenticationResponse.class)
    @RequestMapping(value = "refresh", method = RequestMethod.GET)
    public JwtAuthenticationResponse refresh(HttpServletRequest request) {
        Date refreshTime = new Date(System.currentTimeMillis());
        String token = request.getHeader(AppConstant.JWT_HEADER).substring(7);
        String username = jwtTokenUtil.getUsernameFromToken(token);
        JwtUser user =  (JwtUser)service.loadUserByUsername(username);
        if (jwtTokenUtil.canTokenBeRefreshed(token, user.getLastPasswordResetDate())) {
            final String  refreshToken = jwtTokenUtil.refreshToken(token);
            return new JwtAuthenticationResponse(refreshToken,username,Boolean.TRUE,refreshTime);
        } else {
            throw new AccountExpiredException("登录已过期，请重新登录");
        }
    }

    @ApiOperation(value = "登出", notes = "返回值:{\"success\": true}", response = JSONObject.class)
    @PostMapping("exit")
    public JSONObject logout(HttpServletRequest request) {
        String authToken = request.getHeader(AppConstant.JWT_HEADER).substring(7);
        String loginLogId  = jwtTokenUtil.getLoginId(authToken);
        String jwt_id = jwtTokenUtil.getJwtId(authToken);
        JSONObject result = new JSONObject();
        service.exit(loginLogId ,jwt_id);
        result.put("success",Boolean.TRUE);
        return result;
    }

    @ApiOperation(value = "注册" , notes = "注册",response = Response.class )
    @PutMapping("register")
    public Response update(@RequestBody AddUser user){
        Response response = new Response();
        response.setSuccess(Boolean.TRUE);
        response.setData(new UiUser(userService.add(user)));
        return response;
    }
}
